<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>知识图谱</title>
    <script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js"></script>
    <style>
        body {
            margin: 0;
            padding: 0;
            background: #FAFAFA;
            overflow: hidden;
        }

        #graph-container {
            width: 100vw;
            height: 100vh;
            background: #FAFAFA;
            position: relative;
        }


        .loading-overlay {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(255, 255, 255, 0.8);
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            z-index: 1000;
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
        }

        .spinner {
            width: 40px;
            height: 40px;
            border: 4px solid #e2e8f0;
            border-top: 4px solid #3b82f6;
            border-radius: 50%;
        }

        .loading-text {
            margin-top: 16px;
            color: #64748b;
            font-size: 14px;
        }

        .error-message {
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            text-align: center;
            color: #ef4444;
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
            z-index: 1001;
        }

        /* 权重过滤面板样式 */
        .weight-filter-panel {
            position: fixed;
            bottom: 16px;
            left: 16px;
            background: rgba(255, 255, 255, 0.95);
            border: 1px solid #e2e8f0;
            border-radius: 12px;
            padding: 16px;
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
            min-width: 280px;
            z-index: 150;
        }

        .weight-filter-header {
            display: flex;
            align-items: center;
            gap: 8px;
            margin-bottom: 12px;
            padding-bottom: 8px;
            border-bottom: 1px solid rgba(59, 130, 246, 0.2);
        }

        .weight-filter-icon {
            font-size: 16px;
        }

        .weight-filter-title {
            font-size: 14px;
            font-weight: 600;
            color: #1e293b;
        }

        .weight-filter-content {
            display: flex;
            flex-direction: column;
            gap: 8px;
        }

        .weight-values {
            display: flex;
            justify-content: space-between;
            font-size: 11px;
            color: #6b7280;
        }

        .weight-current {
            font-weight: 700;
            color: #3b82f6;
            font-size: 12px;
        }

        .slider-wrapper {
            position: relative;
            width: 100%;
            height: 8px;
            margin: 8px 0;
        }

        .weight-slider {
            position: absolute;
            width: 100%;
            height: 8px;
            background: transparent;
            outline: none;
            opacity: 0;
            cursor: pointer;
            z-index: 2;
        }

        .weight-slider::-webkit-slider-thumb {
            appearance: none;
            width: 20px;
            height: 20px;
            background: #3b82f6;
            border: 3px solid white;
            border-radius: 50%;
            cursor: pointer;
            box-shadow: 0 2px 4px rgba(59, 130, 246, 0.3);
        }

        .slider-track {
            position: absolute;
            width: 100%;
            height: 8px;
            background: #e2e8f0;
            border-radius: 4px;
            top: 0;
        }

        .slider-progress {
            position: absolute;
            height: 8px;
            background: #3b82f6;
            border-radius: 4px;
            top: 0;
            width: 0%;
        }

        .weight-info {
            display: flex;
            align-items: center;
            justify-content: center;
            margin-top: 4px;
        }

        .visible-nodes {
            font-size: 11px;
            color: #6b7280;
            background: rgba(59, 130, 246, 0.1);
            padding: 3px 8px;
            border-radius: 10px;
            border: 1px solid rgba(59, 130, 246, 0.2);
        }

        /* 统计信息面板样式 - 移动端隐藏 */
        .stats-panel {
            display: none !important; /* 手机端隐藏统计面板 */
            /* 保留样式定义以便将来PC端使用 */
            position: fixed;
            top: 16px;
            left: 16px;
            background: rgba(255, 255, 255, 0.9);
            padding: 12px;
            border-radius: 8px;
            border: 1px solid #e2e8f0;
            box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
            flex-direction: column;
            gap: 8px;
            z-index: 100;
        }

        .stats-item {
            display: flex;
            align-items: center;
            gap: 8px;
        }

        .stats-label {
            font-size: 12px;
            color: #6b7280;
        }

        .stats-value {
            font-size: 14px;
            font-weight: 600;
            color: #3b82f6;
        }
    </style>
</head>
<body>
    <div id="graph-container"></div>

    <div id="loading" class="loading-overlay" style="display: none;">
        <div class="spinner"></div>
        <div class="loading-text">正在加载知识图谱...</div>
    </div>

    <!-- 权重过滤面板 -->
    <div id="weight-filter-panel" class="weight-filter-panel" style="display: none;">
        <div class="weight-filter-header">
            <span class="weight-filter-icon">⚖️</span>
            <span class="weight-filter-title">权重过滤</span>
        </div>
        <div class="weight-filter-content">
            <div class="weight-values">
                <span class="weight-min" id="weight-min">0.000</span>
                <span class="weight-current" id="weight-current">0.000</span>
                <span class="weight-max" id="weight-max">1.000</span>
            </div>
            <div class="slider-wrapper">
                <input
                    type="range"
                    class="weight-slider"
                    id="weight-slider"
                    min="0"
                    max="1"
                    step="0.001"
                    value="0"
                />
                <div class="slider-track"></div>
                <div class="slider-progress" id="slider-progress"></div>
            </div>
            <div class="weight-info">
                <span class="visible-nodes" id="visible-nodes">显示节点: 0</span>
            </div>
        </div>
    </div>

    <!-- 统计信息面板 -->
    <div id="stats-panel" class="stats-panel">
        <div class="stats-item">
            <span class="stats-label">节点数:</span>
            <span class="stats-value" id="node-count">0</span>
        </div>
        <div class="stats-item">
            <span class="stats-label">关系数:</span>
            <span class="stats-value" id="edge-count">0</span>
        </div>
        <div class="stats-item">
            <span class="stats-label">显示:</span>
            <span class="stats-value" id="visible-count">0</span>
        </div>
    </div>

    <!-- 节点详情弹窗 -->
    <div id="nodeDetailsModal" style="
        display: none;
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        background-color: rgba(0, 0, 0, 0.5);
        z-index: 2000;
        overflow-y: auto;
    ">
        <div style="
            position: relative;
            margin: 15vh auto;
            width: 90%;
            max-width: 500px;
            height: 70vh;
            background-color: white;
            border-radius: 12px;
            box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
            overflow: hidden;
            display: flex;
            flex-direction: column;
        ">
            <!-- 弹窗头部 -->
            <div style="
                background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
                color: white;
                padding: 20px;
                text-align: center;
                position: relative;
            ">
                <button onclick="hideNodeDetailsModal()" style="
                    position: absolute;
                    top: 10px;
                    right: 15px;
                    background: none;
                    border: none;
                    color: white;
                    font-size: 24px;
                    cursor: pointer;
                    width: 30px;
                    height: 30px;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                ">&times;</button>
                <h2 id="modalNodeName" style="
                    margin: 0;
                    font-size: 20px;
                    font-weight: bold;
                ">节点详情</h2>
                <p id="modalNodeType" style="
                    margin: 5px 0 0 0;
                    font-size: 14px;
                    opacity: 0.9;
                ">概念</p>
            </div>

            <!-- 弹窗内容 -->
            <div style="padding: 20px; flex: 1; overflow-y: auto;">
                <!-- 节点信息 -->
                <div style="margin-bottom: 20px;">
                    <h3 style="
                        margin: 0 0 10px 0;
                        font-size: 16px;
                        color: #333;
                        border-bottom: 2px solid #f0f0f0;
                        padding-bottom: 5px;
                    ">节点信息</h3>
                    <div id="nodeInfoContent" style="
                        font-size: 14px;
                        line-height: 1.6;
                        color: #666;
                    ">
                        <!-- 动态填充节点信息 -->
                    </div>
                </div>

                <!-- 关联信息 -->
                <div style="margin-bottom: 20px;">
                    <h3 style="
                        margin: 0 0 10px 0;
                        font-size: 16px;
                        color: #333;
                        border-bottom: 2px solid #f0f0f0;
                        padding-bottom: 5px;
                    ">关联信息</h3>
                    <div id="adjacentInfo" style="
                        font-size: 14px;
                        line-height: 1.6;
                        color: #666;
                    ">
                        <!-- 动态填充关联信息 -->
                    </div>
                </div>

                <!-- 建议问题 -->
                <div style="margin-bottom: 20px;">
                    <h3 style="
                        margin: 0 0 10px 0;
                        font-size: 16px;
                        color: #333;
                        border-bottom: 2px solid #f0f0f0;
                        padding-bottom: 5px;
                    ">智能问答</h3>
                    <div id="suggestedQuestions" style="
                        display: flex;
                        flex-direction: column;
                        gap: 8px;
                    ">
                        <!-- 动态填充建议问题 -->
                    </div>
                </div>

                <!-- 操作按钮 -->
                <div style="
                    display: flex;
                    gap: 10px;
                    justify-content: center;
                    margin-top: 20px;
                ">
                    <button onclick="focusToSelectedNode()" style="
                        background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
                        color: white;
                        border: none;
                        padding: 10px 20px;
                        border-radius: 6px;
                        cursor: pointer;
                        font-size: 14px;
                    ">聚焦节点</button>
                    <button onclick="clearNodeSelection()" style="
                        background: #f8f9fa;
                        color: #333;
                        border: 1px solid #ddd;
                        padding: 10px 20px;
                        border-radius: 6px;
                        cursor: pointer;
                        font-size: 14px;
                    ">清除选中</button>
                </div>
            </div>
        </div>
    </div>

    <script>
        // 全局变量
        let chart = null;
        let graphData = { nodes: [], edges: [] };
        let allNodes = [];
        let allLinks = [];
        let layoutType = 'force';
        let isLoading = false;
        let weightRange = { min: 1, max: 10 };
        let currentWeightFilter = 1;
        let filterDebounceTimer = null;
        let isFiltering = false;
        let selectedNodeId = null;
        let highlightedElements = { nodes: [], edges: [] };

        // 实体类型映射
        const ENTITY_TYPE_MAP = {
            'PERSON': 0,
            'ORG': 1,
            'ORGANIZATION': 1,
            'CONCEPT': 2,
            'GPE': 3,
            'LOCATION': 3,
            'EVENT': 4
        };

        // 动态颜色配置 - 与Vue项目保持一致
        const DYNAMIC_COLORS = [
            '#3B82F6', '#10B981', '#8B5CF6', '#EF4444', '#F59E0B',
            '#06B6D4', '#84CC16', '#EC4899', '#6366F1', '#F97316'
        ];


        // 生成动态颜色映射
        function generateTypeColors(typeList) {
            const colorMap = {};
            typeList.forEach((type, index) => {
                colorMap[type] = DYNAMIC_COLORS[index % DYNAMIC_COLORS.length];
            });
            return colorMap;
        }

        // 获取节点颜色 - 简化并强制多样化的颜色分配
        function getNodeColor(nodeType, colorMap) {
            const standardizedType = (nodeType || 'CONCEPT').toUpperCase();

            // 优先使用动态颜色映射
            if (colorMap && colorMap[standardizedType]) {
                console.log('Using dynamic color for', standardizedType + ':', colorMap[standardizedType]);
                return colorMap[standardizedType];
            }

            // 人工分组类型的固定颜色
            const artificialTypeColors = {
                'TYPE_A': '#3B82F6',    // 蓝色
                'TYPE_B': '#10B981',    // 绿色
                'TYPE_C': '#8B5CF6',    // 紫色
                'TYPE_D': '#EF4444',    // 红色
                'TYPE_DEFAULT': '#F59E0B'  // 橙色
            };

            if (artificialTypeColors[standardizedType]) {
                console.log('Using artificial type color for', standardizedType + ':', artificialTypeColors[standardizedType]);
                return artificialTypeColors[standardizedType];
            }

            // 预定义实体类型颜色
            const entityTypeColors = {
                'PERSON': '#3B82F6',
                'ORGANIZATION': '#10B981',
                'CONCEPT': '#8B5CF6',
                'LOCATION': '#EF4444',
                'EVENT': '#F59E0B'
            };

            if (entityTypeColors[standardizedType]) {
                console.log('Using entity type color for', standardizedType + ':', entityTypeColors[standardizedType]);
                return entityTypeColors[standardizedType];
            }

            // 最后的回退：基于哈希的颜色选择
            const hash = standardizedType.split('').reduce((a, b) => {
                a = ((a << 5) - a) + b.charCodeAt(0);
                return a & a;
            }, 0);
            const colorIndex = Math.abs(hash) % DYNAMIC_COLORS.length;
            const fallbackColor = DYNAMIC_COLORS[colorIndex];

            console.log('Using fallback hash color for', standardizedType + ':', fallbackColor);
            return fallbackColor;
        }

        // 获取节点大小 - 基于权重动态调整，适合显示文字
        function getNodeSize(weight) {
            const baseSize = 50;  // 再次大幅增大基础尺寸
            const maxSize = 80;   // 增大最大尺寸
            const minSize = 38;   // 增大最小尺寸
            const scaledSize = baseSize + (weight - 1) * 6;
            return Math.min(Math.max(scaledSize, minSize), maxSize);
        }


        // 初始化图表
        function initChart() {
            try {
                const container = document.getElementById('graph-container');
                if (!container) {
                    console.error('Graph container not found');
                    return;
                }

                chart = echarts.init(container);

                // 设置高质量默认配置 - 关闭所有动画提升性能
                const option = {
                    backgroundColor: 'transparent',
                    animation: false,
                    animationDuration: 0,
                    animationDurationUpdate: 0,
                    series: [{
                        name: 'Knowledge Graph',
                        type: 'graph',
                        layout: 'force',
                        data: [],
                        links: [],
                        categories: [],
                        roam: true,
                        focusNodeAdjacency: false,
                        draggable: false,
                        edgeSymbol: ['none', 'none'],
                        zoom: 1.0, // 默认缩放为1.0显示完整图谱
                        tooltip: {
                            show: false
                        },
                        lineStyle: {
                            color: 'source',
                            curveness: 0,
                            opacity: 0.6
                        },
                        label: {
                            show: true
                        },
                        emphasis: {
                            focus: 'adjacency',
                            lineStyle: {
                                width: 4,
                                color: '#3B82F6',
                                shadowBlur: 8,
                                shadowColor: 'rgba(59, 130, 246, 0.4)'
                            },
                            label: {
                                show: true,
                                fontSize: 14,
                                fontWeight: 'bold',
                                color: '#ffffff'
                            },
                            itemStyle: {
                                borderWidth: 4,
                                borderColor: '#3B82F6',
                                shadowBlur: 12,
                                shadowColor: 'rgba(59, 130, 246, 0.3)'
                            }
                        },
                        force: {
                            repulsion: 2200, // 节点非常大，大幅增加排斥力
                            gravity: 0.06,   // 减弱向心力给节点更多空间
                            edgeLength: [160, 280], // 大幅增加连线长度适应超大节点
                            layoutAnimation: false
                        }
                    }]
                };

                chart.setOption(option);

                // 绑定事件
                bindChartEvents();

                // 窗口大小变化时重新调整图表
                window.addEventListener('resize', function() {
                    if (chart) {
                        chart.resize();
                    }
                });

                console.log('Chart initialized successfully');

                // 初始化完成后隐藏loading
                hideLoading();

                // 通知鸿蒙应用WebView已准备就绪
                sendMessageToHarmony('webview-ready', {});

            } catch (error) {
                console.error('Failed to initialize chart:', error);
                showError('图表初始化失败: ' + error.message);
            }
        }

        // 绑定图表事件
        function bindChartEvents() {
            if (!chart) {
                console.error('Chart is not available for event binding');
                return;
            }

            console.log('Binding chart events...');

            // 节点点击事件
            chart.on('click', function(params) {
                console.log('Chart click event triggered:', params);
                if (params.dataType === 'node') {
                    console.log('Node click detected:', params.data);
                    handleNodeClick(params.data);
                } else {
                    console.log('Non-node click, dataType:', params.dataType);
                }
            });

            // 节点悬停事件
            chart.on('mouseover', function(params) {
                if (params.dataType === 'node') {
                    handleNodeHover(params.data);
                }
            });

            // 图表完成渲染事件（由于关闭了动画，finished事件可能不触发）
            chart.on('finished', function() {
                hideLoading();
            });

            // 确保loading在图表设置完成后隐藏
            setTimeout(() => {
                hideLoading();
            }, 500);

        }

        // 处理节点点击 - 显示WebView内部弹窗
        function handleNodeClick(nodeData) {
            console.log('Node clicked:', nodeData);

            try {
                const nodeId = nodeData.id;

                // 如果点击的是已选中节点，则取消选中并关闭弹窗
                if (selectedNodeId === nodeId) {
                    selectedNodeId = null;
                    highlightedElements = { nodes: [], edges: [] };
                    clearHighlight();
                    hideNodeDetailsModal();
                    return;
                }

                // 选中新节点
                selectedNodeId = nodeId;

                // 找到相邻的节点和边
                const adjacentElements = getAdjacentElements(nodeId);
                highlightedElements = adjacentElements;

                // 高亮选中节点和相邻元素
                highlightSelectedNode(nodeData, adjacentElements);

                // 显示节点详情弹窗
                showNodeDetailsModal({
                    selectedNode: nodeData,
                    adjacentNodes: adjacentElements.nodes.length,
                    adjacentEdges: adjacentElements.edges.length,
                    suggestedQuestions: [
                        '这个' + (nodeData.entity_type || '概念') + '是什么？',
                        '请详细介绍' + (nodeData.name || nodeData.entity_name),
                        '与' + (nodeData.name || nodeData.entity_name) + '相关的内容有哪些？'
                    ]
                });

                console.log('Selected node:', nodeId, 'Adjacent elements:', adjacentElements);

            } catch (error) {
                console.error('Error in handleNodeClick:', error);
                showError('节点点击处理失败: ' + error.message);
            }
        }

        // 处理节点悬停
        function handleNodeHover(nodeData) {
            sendMessageToHarmony('node-hover', {
                id: nodeData.id,
                name: nodeData.name || nodeData.entity_name,
                entity_name: nodeData.entity_name,
                entity_type: nodeData.entity_type,
                weight: nodeData.weight,
                category: nodeData.category
            });
        }

        // 获取节点的相邻元素（邻居节点和连接的边）
        function getAdjacentElements(nodeId) {
            const adjacentNodes = [];
            const adjacentEdges = [];

            // 找到与该节点相连的所有边
            graphData.edges.forEach(edge => {
                if (edge.source === nodeId || edge.target === nodeId) {
                    adjacentEdges.push(edge);

                    // 添加相邻节点
                    const neighborId = edge.source === nodeId ? edge.target : edge.source;
                    if (!adjacentNodes.includes(neighborId)) {
                        adjacentNodes.push(neighborId);
                    }
                }
            });

            return {
                nodes: adjacentNodes,
                edges: adjacentEdges
            };
        }

        // 高亮选中节点和相邻元素
        function highlightSelectedNode(selectedNode, adjacentElements) {
            if (!chart || !graphData.nodes.length) return;

            try {
                // 首先清除所有高亮
                clearHighlight();

                // 高亮选中的节点（使用不同的样式表示选中状态）
                const selectedNodeIndex = graphData.nodes.findIndex(node => node.id === selectedNode.id);
                if (selectedNodeIndex >= 0) {
                    chart.dispatchAction({
                        type: 'highlight',
                        seriesIndex: 0,
                        dataIndex: selectedNodeIndex
                    });
                }

                // 高亮相邻节点
                adjacentElements.nodes.forEach(neighborId => {
                    const neighborIndex = graphData.nodes.findIndex(node => node.id === neighborId);
                    if (neighborIndex >= 0) {
                        chart.dispatchAction({
                            type: 'highlight',
                            seriesIndex: 0,
                            dataIndex: neighborIndex
                        });
                    }
                });

                console.log('Highlighted node:', selectedNode.id, 'and', adjacentElements.nodes.length, 'neighbors');

            } catch (error) {
                console.error('Failed to highlight selected node:', error);
            }
        }

        // 清除所有高亮
        function clearHighlight() {
            if (!chart) return;

            try {
                chart.dispatchAction({
                    type: 'downplay',
                    seriesIndex: 0
                });
            } catch (error) {
                console.error('Failed to clear highlight:', error);
            }
        }

        // 高亮节点（保留原有功能）
        function highlightNode(nodeId) {
            if (!chart || !graphData.nodes.length) return;

            try {
                chart.dispatchAction({
                    type: 'highlight',
                    seriesIndex: 0,
                    dataIndex: graphData.nodes.findIndex(node => node.id === nodeId)
                });
            } catch (error) {
                console.error('Failed to highlight node:', error);
            }
        }

        // 设置图谱数据
        function setGraphData(data, isClearingData = false) {
            try {
                console.log('=== WebView setGraphData 被调用 ===');

                if (!data) {
                    console.error('数据为空');
                    showError('未接收到图谱数据');
                    return;
                }

                // 验证数据结构
                const nodes = data.nodes || [];
                const edges = data.edges || [];

                if (!Array.isArray(nodes) || !Array.isArray(edges)) {
                    console.error('数据格式错误 - nodes或edges不是数组');
                    showError('图谱数据格式错误');
                    return;
                }

                console.log(`接收到数据: ${nodes.length}个节点, ${edges.length}条边`);

                if (nodes.length === 0) {
                    console.warn('没有节点数据');
                    // 只在非清空操作时显示错误
                    if (!isClearingData) {
                        showError('没有可显示的节点');
                    }
                    return;
                }

                // 存储原始数据
                allNodes = nodes;
                allLinks = edges;

                // 打印数据样本用于调试
                if (nodes.length > 0) {
                    console.log('节点样本:', nodes.slice(0, 2));
                }
                if (edges.length > 0) {
                    console.log('边样本:', edges.slice(0, 2));
                }

                // 计算权重范围
                if (nodes.length > 0) {
                    const weights = nodes.map(node => node.weight || 1);
                    weightRange.min = Math.min(...weights);
                    weightRange.max = Math.max(...weights);
                    currentWeightFilter = weightRange.min;
                    console.log('权重范围:', weightRange);
                }

                // 初始化权重滑动器
                initWeightFilter();

                // 应用默认过滤并显示图表
                applyWeightFilter(currentWeightFilter, true);

                console.log('=== 图表数据设置完成 ===');

            } catch (error) {
                console.error('设置图谱数据失败:', error);
                showError('数据处理失败: ' + error.message);
            }
        }

        // 初始化权重过滤器
        function initWeightFilter() {
            const weightSlider = document.getElementById('weight-slider');
            const weightFilterPanel = document.getElementById('weight-filter-panel');

            if (!weightSlider || !weightFilterPanel) return;

            // 设置滑动器范围
            weightSlider.min = weightRange.min;
            weightSlider.max = weightRange.max;
            weightSlider.step = (weightRange.max - weightRange.min) / 1000;
            weightSlider.value = currentWeightFilter;

            // 更新显示
            updateWeightDisplay();

            // 显示权重过滤面板
            weightFilterPanel.style.display = 'block';

            // 绑定滑动器事件（使用防抖优化性能）
            weightSlider.addEventListener('input', function(event) {
                currentWeightFilter = parseFloat(event.target.value);
                updateWeightDisplay();

                // 防抖处理，避免频繁更新
                debounceFilterUpdate();
            });

            console.log('Weight filter initialized');
        }

        // 更新权重显示
        function updateWeightDisplay() {
            const weightMin = document.getElementById('weight-min');
            const weightMax = document.getElementById('weight-max');
            const weightCurrent = document.getElementById('weight-current');
            const sliderProgress = document.getElementById('slider-progress');

            if (weightMin) weightMin.textContent = weightRange.min.toFixed(3);
            if (weightMax) weightMax.textContent = weightRange.max.toFixed(3);
            if (weightCurrent) weightCurrent.textContent = currentWeightFilter.toFixed(3);

            // 更新滑动器进度条
            if (sliderProgress) {
                const progress = ((currentWeightFilter - weightRange.min) / (weightRange.max - weightRange.min)) * 100;
                sliderProgress.style.width = progress + '%';
            }
        }

        // 应用权重过滤
        function applyWeightFilter(minWeight, limitTo300 = false) {
            try {
                // 按权重过滤节点
                let filteredNodes = allNodes.filter(node => (node.weight || 1) >= minWeight);

                // 如果需要限制到300个节点，则按权重排序并取前300个
                if (limitTo300 && filteredNodes.length > 500) {
                    filteredNodes = filteredNodes
                        .sort((a, b) => (b.weight || 1) - (a.weight || 1))
                        .slice(0, 500);
                }

                // 获取过滤后节点的ID集合
                const nodeIds = new Set(filteredNodes.map(node => node.id));

                // 过滤相关的边
                const filteredLinks = allLinks.filter(link =>
                    nodeIds.has(link.source) && nodeIds.has(link.target)
                );

                // 处理过滤后的数据
                processAndUpdateGraph(filteredNodes, filteredLinks);

                // 更新统计信息
                updateStats(filteredNodes.length, filteredLinks.length);

                // 确保在数据过滤完成后隐藏loading
                setTimeout(() => {
                    hideLoading();
                }, 200);

                console.log('Applied weight filter:', minWeight, 'Nodes:', filteredNodes.length, 'Edges:', filteredLinks.length);

            } catch (error) {
                console.error('Failed to apply weight filter:', error);
                showError('权重过滤失败: ' + error.message);
            }
        }

        // 处理并更新图表
        function processAndUpdateGraph(nodes, edges) {
            // 为了确保不同颜色，我们使用更强制的方法
            // 如果只有一种类型，我们人工创建多种类型进行颜色分配

            let uniqueTypes = [...new Set(nodes.map(node => {
                const rawType = node.entity_type || node.type || 'CONCEPT';
                return rawType.toUpperCase();
            }))];

            console.log('Original unique types:', uniqueTypes);

            // 如果只有一种或很少类型，我们基于节点名称或其他属性创建人工分组
            if (uniqueTypes.length <= 2) {
                console.log('Too few types detected, creating artificial grouping...');

                // 基于节点名称的首字母或其他特征进行分组
                const artificialTypes = [];
                nodes.forEach(node => {
                    const name = (node.name || node.entity_name || '').toUpperCase();
                    if (name.length > 0) {
                        const firstChar = name.charAt(0);
                        if (firstChar >= 'A' && firstChar <= 'F') {
                            artificialTypes.push('TYPE_A');
                        } else if (firstChar >= 'G' && firstChar <= 'M') {
                            artificialTypes.push('TYPE_B');
                        } else if (firstChar >= 'N' && firstChar <= 'S') {
                            artificialTypes.push('TYPE_C');
                        } else {
                            artificialTypes.push('TYPE_D');
                        }
                    } else {
                        artificialTypes.push('TYPE_DEFAULT');
                    }
                });

                uniqueTypes = [...new Set(artificialTypes)];
                console.log('Generated artificial types:', uniqueTypes);
            }

            const colorMap = generateTypeColors(uniqueTypes);
            console.log('Final color map:', colorMap);

            // 处理节点数据 - 使用新的类型分组
            const processedNodes = nodes.map((node, index) => {
                let nodeType;

                if (uniqueTypes.length > 2) {
                    // 使用原始类型
                    const rawType = node.entity_type || node.type || 'CONCEPT';
                    nodeType = rawType.toUpperCase();
                } else {
                    // 使用人工分组
                    const name = (node.name || node.entity_name || '').toUpperCase();
                    if (name.length > 0) {
                        const firstChar = name.charAt(0);
                        if (firstChar >= 'A' && firstChar <= 'F') {
                            nodeType = 'TYPE_A';
                        } else if (firstChar >= 'G' && firstChar <= 'M') {
                            nodeType = 'TYPE_B';
                        } else if (firstChar >= 'N' && firstChar <= 'S') {
                            nodeType = 'TYPE_C';
                        } else {
                            nodeType = 'TYPE_D';
                        }
                    } else {
                        nodeType = 'TYPE_DEFAULT';
                    }
                }

                const weight = node.weight || 1;
                const nodeColor = getNodeColor(nodeType, colorMap);

                // 对前10个节点打印调试信息
                if (index < 10) {
                    console.log('Processing node ' + index + ':', {
                        name: node.name || node.entity_name,
                        final_type: nodeType,
                        assigned_color: nodeColor
                    });
                }

                return {
                    id: node.id,
                    name: node.name || node.entity_name,
                    entity_name: node.entity_name,
                    entity_type: nodeType,
                    weight: weight,
                    category: nodeType,
                    symbol: 'circle',
                    symbolSize: getNodeSize(weight),
                    itemStyle: {
                        color: nodeColor,
                        borderColor: '#ffffff',
                        borderWidth: 2
                    },
                    label: {
                        show: true,
                        position: 'inside',
                        formatter: function(params) {
                            const name = params.data.name;
                            return name.length > 8 ? name.substring(0, 8) + '...' : name;
                        },
                        fontSize: function(params) {
                            const nodeSize = params.data.symbolSize || 50;
                            return Math.max(14, Math.min(18, nodeSize * 0.32));
                        },
                        color: '#ffffff',
                        fontWeight: 'bold',
                        textAlign: 'center',
                        textShadowColor: 'rgba(0, 0, 0, 0.5)',
                        textShadowBlur: 2
                    },
                    emphasis: {
                        itemStyle: {
                            borderWidth: 3,
                            color: nodeColor // 确保高亮时颜色一致
                        },
                        label: {
                            show: true,
                            fontSize: 12,
                            fontWeight: 'bold'
                        }
                    }
                };
            });

            // 处理边数据 - 根据源节点颜色设置边的颜色
            const processedEdges = edges.map(edge => {
                // 找到源节点以获取其颜色
                const sourceNode = processedNodes.find(node => node.id === edge.source);
                const edgeColor = sourceNode ? sourceNode.itemStyle.color : '#999999';

                return {
                    source: edge.source,
                    target: edge.target,
                    relation_type: edge.relation_type || '关系',
                    weight: edge.weight || 1,
                    value: edge.weight || 1,
                    lineStyle: {
                        width: Math.max(1, Math.min(3, (edge.weight || 1) * 1.2)),
                        opacity: 0.6,
                        color: edgeColor // 使用源节点颜色
                    },
                    label: {
                        show: false,
                        position: 'middle',
                        rotate: 0,
                        backgroundColor: 'rgba(255, 255, 255, 0.8)',
                        borderColor: 'rgba(200, 200, 200, 0.3)',
                        borderWidth: 0.5,
                        borderRadius: 4,
                        padding: [2, 6],
                        fontSize: 10,
                        color: '#666666',
                        formatter: function(params) {
                            let text = params.data.relation_type;
                            return text.length > 15 ? text.substring(0, 15) + '...' : text;
                        }
                    },
                    emphasis: {
                        label: {
                            show: true,
                            backgroundColor: 'rgba(255, 255, 255, 0.95)',
                            borderColor: 'rgba(102, 102, 102, 0.4)',
                            color: '#333333',
                            fontSize: 11
                        },
                        lineStyle: {
                            width: 3,
                            opacity: 1,
                            color: edgeColor // 高亮时也使用相同颜色
                        }
                    }
                };
            });

            // 生成类别配置，确保每个类别都有正确的颜色
            const categories = uniqueTypes.map(type => {
                const categoryColor = getNodeColor(type, colorMap);
                console.log('Category', type, 'assigned color:', categoryColor);
                return {
                    name: type,
                    itemStyle: {
                        color: categoryColor
                    }
                };
            });

            graphData = {
                nodes: processedNodes,
                edges: processedEdges,
                categories: categories
            };

            // 更新图表
            updateChart();

            // 确保图表更新完成后隐藏loading
            setTimeout(() => {
                hideLoading();
            }, 300);
        }

        // 更新统计信息
        function updateStats(nodeCount, edgeCount) {
            const nodeCountEl = document.getElementById('node-count');
            const edgeCountEl = document.getElementById('edge-count');
            const visibleCountEl = document.getElementById('visible-count');
            const visibleNodesEl = document.getElementById('visible-nodes');

            if (nodeCountEl) nodeCountEl.textContent = allNodes.length;
            if (edgeCountEl) edgeCountEl.textContent = allLinks.length;
            if (visibleCountEl) visibleCountEl.textContent = nodeCount;
            if (visibleNodesEl) visibleNodesEl.textContent = '显示节点: ' + nodeCount;
        }


        // 防抖过滤更新
        function debounceFilterUpdate() {
            // 清除之前的定时器
            if (filterDebounceTimer) {
                clearTimeout(filterDebounceTimer);
            }

            // 设置新的定时器
            filterDebounceTimer = setTimeout(() => {
                applyWeightFilter(currentWeightFilter, false);
            }, 100); // 100ms防抖延迟
        }

        // 性能优化的图表更新 - 完全关闭动画
        function updateChart() {
            if (!chart || !graphData || isFiltering) return;

            try {
                isFiltering = true;
                showLoading();

                const option = {
                    animation: false,
                    animationDuration: 0,
                    animationDurationUpdate: 0,
                    series: [{
                        data: graphData.nodes,
                        links: graphData.edges,
                        categories: graphData.categories,
                        layout: layoutType,
                        animation: false, // 完全关闭动画
                        force: {
                            repulsion: Math.max(1500, Math.min(2800, 2200 - graphData.nodes.length * 3)), // 节点超大，大幅增加基础排斥力
                            gravity: 0.06,
                            edgeLength: [140, 240], // 适应超大节点的连线长度
                            layoutAnimation: false // 关闭布局动画
                        }
                    }]
                };

                chart.setOption(option, false, true);

                // 立即设置缩放和隐藏loading
                setTimeout(() => {
                    setDefaultZoom();
                    isFiltering = false;
                    hideLoading();
                }, 100);

            } catch (error) {
                console.error('Failed to update chart:', error);
                isFiltering = false;
                hideLoading();
                showError('图表更新失败: ' + error.message);
            }
        }

        // 优化的默认缩放设置
        function setDefaultZoom() {
            if (!chart || isFiltering) return;

            try {
                const centerX = chart.getWidth() / 2;
                const centerY = chart.getHeight() / 2;

                // 根据节点数量动态调整缩放比例，尽量显示全图
                let zoomSize = 1.0; // 默认显示完整图谱
                if (graphData.nodes.length > 300) {
                    zoomSize = 0.6; // 节点很多时适当缩小
                } else if (graphData.nodes.length > 200) {
                    zoomSize = 0.7;
                } else if (graphData.nodes.length > 100) {
                    zoomSize = 0.8;
                } else if (graphData.nodes.length < 20) {
                    zoomSize = 1.2; // 节点很少时适当放大
                }

                chart.dispatchAction({
                    type: 'graphRoam',
                    zoom: zoomSize,
                    x: centerX,
                    y: centerY
                });

                console.log('Optimized zoom set to', zoomSize + 'x for', graphData.nodes.length, 'nodes');
            } catch (error) {
                console.warn('Failed to set optimized zoom:', error);
            }
        }

        // 设置加载状态
        function setLoading(loading) {
            isLoading = loading;
            if (loading) {
                showLoading();
            } else {
                hideLoading();
            }
        }

        // 显示加载动画
        function showLoading() {
            const loadingEl = document.getElementById('loading');
            if (loadingEl) {
                loadingEl.style.display = 'flex';
            }
        }

        // 隐藏加载动画
        function hideLoading() {
            const loadingEl = document.getElementById('loading');
            if (loadingEl) {
                loadingEl.style.display = 'none';
            }
        }

        // 显示错误信息
        function showError(message) {
            hideLoading();

            // 移除已存在的错误信息
            const existingError = document.querySelector('.error-message');
            if (existingError) {
                existingError.remove();
            }

            // 创建新的错误信息
            const errorDiv = document.createElement('div');
            errorDiv.className = 'error-message';
            errorDiv.innerHTML = `
                <div style="font-size: 18px; font-weight: bold; margin-bottom: 8px;">错误</div>
                <div style="font-size: 14px;">${message}</div>
            `;

            document.body.appendChild(errorDiv);

            // 3秒后自动隐藏
            setTimeout(() => {
                if (errorDiv.parentNode) {
                    errorDiv.parentNode.removeChild(errorDiv);
                }
            }, 3000);
        }

        // 重置视图
        function reset() {
            try {
                if (chart) {
                    // 恢复缩放
                    chart.dispatchAction({
                        type: 'restore'
                    });

                    // 清除高亮
                    chart.dispatchAction({
                        type: 'downplay'
                    });

                    console.log('Chart view reset');
                }
            } catch (error) {
                console.error('Failed to reset chart:', error);
            }
        }

        // 更改布局 - 支持多种布局类型
        function updateLayout(layout) {
            layoutType = layout || 'force';
            console.log('Switching to layout:', layoutType);

            if (chart && graphData && graphData.nodes.length > 0) {
                let layoutConfig = {
                    layout: layoutType
                };

                // 根据布局类型设置不同的参数
                if (layoutType === 'force') {
                    layoutConfig.force = {
                        repulsion: 1400,
                        gravity: 0.08,
                        edgeLength: [100, 200],
                        layoutAnimation: true
                    };
                } else if (layoutType === 'circular') {
                    layoutConfig.circular = {
                        rotateLabel: true
                    };
                }

                const option = {
                    series: [{
                        ...layoutConfig,
                        data: graphData.nodes,
                        links: graphData.edges,
                        categories: graphData.categories
                    }]
                };

                chart.setOption(option, false, true);

                // 布局切换后重新设置缩放
                setTimeout(() => {
                    setDefaultZoom();
                }, 800);
            }
        }

        // 搜索节点
        function searchNodes(query) {
            if (!graphData.nodes.length || !query) return;

            let foundCount = 0;
            const matchedNodes = [];

            graphData.nodes.forEach(node => {
                const name = node.name || node.entity_name || '';
                if (name.toLowerCase().includes(query.toLowerCase())) {
                    matchedNodes.push(node);
                    foundCount++;
                }
            });

            if (foundCount > 0) {
                // 高亮匹配的节点
                matchedNodes.forEach(node => {
                    highlightNode(node.id);
                });
            }

            // 发送搜索结果
            sendMessageToHarmony('search-result', {
                query: query,
                count: foundCount,
                nodes: matchedNodes
            });
        }

        // 获取节点类型标签
        function getNodeTypeLabel(category) {
            switch (category) {
                case 0: return '人员';
                case 1: return '组织';
                case 2: return '概念';
                case 3: return '地点';
                case 4: return '事件';
                default: return '未知';
            }
        }

        // 标记桥接是否可用，避免重复警告
        let bridgeWarningShown = false;

        // 向鸿蒙应用发送消息
        function sendMessageToHarmony(event, data) {
            try {
                // 只为重要事件记录日志（非 hover 事件）
                if (event !== 'node-hover') {
                    console.log('Attempting to send message:', event, data);
                }

                if (window.harmonyOS && window.harmonyOS.postMessage) {
                    const message = {
                        event: event,
                        data: data || {}
                    };
                    if (event !== 'node-hover') {
                        console.log('Sending message to HarmonyOS:', JSON.stringify(message));
                    }
                    window.harmonyOS.postMessage(JSON.stringify(message));
                    if (event !== 'node-hover') {
                        console.log('Message sent successfully');
                    }
                } else {
                    // 只显示一次警告，避免日志泛滥
                    if (!bridgeWarningShown) {
                        console.warn('HarmonyOS bridge not available - will not show this warning again');
                        console.log('window.harmonyOS:', window.harmonyOS);
                        bridgeWarningShown = true;
                    }
                }
            } catch (error) {
                console.error('Failed to send message to HarmonyOS:', error);
            }
        }

        // 选中指定节点（供外部调用）
        function selectNode(nodeId) {
            if (!graphData.nodes.length) return;

            const node = graphData.nodes.find(node => node.id === nodeId);
            if (node) {
                handleNodeClick(node);
            } else {
                console.warn('Node not found:', nodeId);
            }
        }

        // 清除选中状态（供外部调用）
        function clearSelection() {
            selectedNodeId = null;
            highlightedElements = { nodes: [], edges: [] };
            clearHighlight();
            sendMessageToHarmony('selection-cleared', {});
        }

        // 获取当前选中节点信息
        function getSelectedNodeInfo() {
            if (!selectedNodeId) return null;

            const selectedNode = graphData.nodes.find(node => node.id === selectedNodeId);
            if (!selectedNode) return null;

            return {
                selectedNode: selectedNode,
                adjacentElements: highlightedElements,
                adjacentCount: highlightedElements.nodes.length
            };
        }

        // 聚焦到指定节点
        function focusToNode(nodeId) {
            if (!chart || !graphData.nodes.length) return;

            const nodeIndex = graphData.nodes.findIndex(node => node.id === nodeId);
            if (nodeIndex < 0) {
                console.warn('Node not found for focus:', nodeId);
                return;
            }

            try {
                // 先选中节点
                selectNode(nodeId);

                // 然后聚焦到节点位置
                setTimeout(() => {
                    chart.dispatchAction({
                        type: 'focusNodeAdjacency',
                        seriesIndex: 0,
                        dataIndex: nodeIndex
                    });

                    console.log('Focused to node:', nodeId);
                }, 300);

            } catch (error) {
                console.error('Failed to focus to node:', error);
            }
        }

        // 创建与鸿蒙的通信桥梁 - 扩展功能
        window.harmonyBridge = {
            // 原有功能
            setGraphData: setGraphData,
            setLoading: setLoading,
            reset: reset,
            updateLayout: updateLayout,
            searchNodes: searchNodes,

            // 新增节点选择相关功能
            selectNode: selectNode,
            clearSelection: clearSelection,
            getSelectedNodeInfo: getSelectedNodeInfo,
            focusToNode: focusToNode,

            // 获取图谱状态
            getGraphStats: function() {
                return {
                    totalNodes: allNodes.length,
                    totalEdges: allLinks.length,
                    visibleNodes: graphData.nodes.length,
                    visibleEdges: graphData.edges.length,
                    selectedNodeId: selectedNodeId,
                    highlightedCount: highlightedElements.nodes.length
                };
            }
        };

        // 调试：确认harmonyBridge已创建
        console.log('HarmonyBridge created with functions:', Object.keys(window.harmonyBridge));
        console.log('setGraphData function available:', typeof window.harmonyBridge.setGraphData === 'function');

        // 节点详情弹窗功能
        function showNodeDetailsModal(data) {
            const modal = document.getElementById('nodeDetailsModal');
            const nodeName = document.getElementById('modalNodeName');
            const nodeType = document.getElementById('modalNodeType');
            const nodeInfoContent = document.getElementById('nodeInfoContent');
            const adjacentInfo = document.getElementById('adjacentInfo');
            const suggestedQuestions = document.getElementById('suggestedQuestions');

            if (!modal || !data.selectedNode) return;

            // 设置头部信息
            nodeName.textContent = data.selectedNode.name || data.selectedNode.entity_name || '未知节点';
            nodeType.textContent = getNodeTypeLabel(data.selectedNode.entity_type) || '概念';

            // 设置节点信息
            nodeInfoContent.innerHTML = `
                <div style="margin-bottom: 8px;"><strong>ID:</strong> ${data.selectedNode.id || 'N/A'}</div>
                <div style="margin-bottom: 8px;"><strong>名称:</strong> ${data.selectedNode.name || data.selectedNode.entity_name || 'N/A'}</div>
                <div style="margin-bottom: 8px;"><strong>类型:</strong> ${data.selectedNode.entity_type || 'CONCEPT'}</div>
                <div style="margin-bottom: 8px;"><strong>权重:</strong> ${data.selectedNode.weight || 1}</div>
            `;

            // 设置关联信息
            adjacentInfo.innerHTML = `
                <div style="margin-bottom: 8px;"><strong>相邻节点:</strong> ${data.adjacentNodes || 0} 个</div>
                <div style="margin-bottom: 8px;"><strong>连接边:</strong> ${data.adjacentEdges || 0} 条</div>
                <div style="margin-bottom: 8px;"><strong>总高亮:</strong> ${(data.adjacentNodes || 0) + 1} 个节点</div>
            `;

            // 设置建议问题
            suggestedQuestions.innerHTML = '';
            if (data.suggestedQuestions && data.suggestedQuestions.length > 0) {
                data.suggestedQuestions.forEach((question, index) => {
                    const questionBtn = document.createElement('button');
                    questionBtn.style.cssText = `
                        background: linear-gradient(135deg, #a8edea 0%, #fed6e3 100%);
                        color: #333;
                        border: none;
                        padding: 10px 15px;
                        border-radius: 20px;
                        cursor: pointer;
                        font-size: 13px;
                        text-align: left;
                        transition: transform 0.2s ease;
                    `;
                    questionBtn.textContent = question;
                    questionBtn.onclick = () => {
                        console.log('Question clicked:', question);
                        // 这里可以添加问答功能
                        alert('问答功能：' + question);
                    };
                    questionBtn.onmouseover = () => {
                        questionBtn.style.transform = 'translateY(-2px)';
                    };
                    questionBtn.onmouseout = () => {
                        questionBtn.style.transform = 'translateY(0)';
                    };
                    suggestedQuestions.appendChild(questionBtn);
                });
            } else {
                suggestedQuestions.innerHTML = '<p style="color: #999; font-style: italic;">暂无建议问题</p>';
            }

            // 显示弹窗
            modal.style.display = 'block';
        }

        function hideNodeDetailsModal() {
            const modal = document.getElementById('nodeDetailsModal');
            if (modal) {
                modal.style.display = 'none';
            }
        }

        function focusToSelectedNode() {
            if (selectedNodeId && chart) {
                console.log('Focusing to node:', selectedNodeId);

                // 找到节点索引
                const nodeIndex = graphData.nodes.findIndex(node => node.id === selectedNodeId);
                if (nodeIndex >= 0) {
                    try {
                        chart.dispatchAction({
                            type: 'focusNodeAdjacency',
                            seriesIndex: 0,
                            dataIndex: nodeIndex
                        });
                    } catch (error) {
                        console.log('Focus action not supported, using highlight instead');
                        chart.dispatchAction({
                            type: 'highlight',
                            seriesIndex: 0,
                            dataIndex: nodeIndex
                        });
                    }
                }
            }
        }

        function clearNodeSelection() {
            selectedNodeId = null;
            highlightedElements = { nodes: [], edges: [] };
            clearHighlight();
            hideNodeDetailsModal();
        }

        function getNodeTypeLabel(entityType) {
            const typeMap = {
                'PERSON': '人员',
                'ORGANIZATION': '组织',
                'ORG': '组织',
                'CONCEPT': '概念',
                'LOCATION': '地点',
                'GPE': '地点',
                'EVENT': '事件',
                'TECHNOLOGY': '技术',
                'METHOD': '方法',
                'DATA': '数据'
            };
            return typeMap[entityType] || '概念';
        }

        // 页面加载完成后初始化（只初始化一次）
        document.addEventListener('DOMContentLoaded', function() {
            console.log('DOM loaded, initializing chart...');
            // 直接初始化，不等待桥接（桥接对核心功能不是必须的）
            if (!chart) {
                initChart();
            }
        });

        // 错误处理
        window.addEventListener('error', function(event) {
            console.error('Global error:', event.error);
            showError('页面发生错误: ' + (event.error?.message || '未知错误'));
        });

    </script>
</body>
</html>